<!--主题详情-->
<script lang="ts" setup>
import {useRoute, useRouter} from "vue-router";
import {nextTick, onMounted, ref, watch} from "vue";
import {useTopicReadStore} from "../../store/TopicReadStore.ts";
import type {TopicDetailData} from "../../network/types/TopicDetail.ts";
import ReplyTable from "../../components/reply/ReplyTable.vue";
import {copyText, setWindowTitle, topicCode, topicUrl} from "../../utils/Utils.ts";
import {useAccountStore} from "../../store/AccountStore.ts";
import TopicReadRoute from "../../components/routes/TopicReadRoute.vue";
import {ElMessage, ElMessageBox} from "element-plus";
import {PostRouteName, ReplyListRoute, TopicListRoute} from "../index.ts";
import ForumRoute from "../../components/routes/ForumRoute.vue";
import ColRoute from "../../components/routes/ColRoute.vue";
import {scrollShortKeys, type ShortKey, showShortKeys} from "../../utils/ShortKeys.ts";
import {scrollToElementBatch, scrollToTop} from "../../utils/ScrollUtils.ts";
import type {ReplyInfo} from "../../network/types/Reply.ts";
import {parseContent} from "../../network/types/BbsCodeNode.ts";
import ReplyFavorDialog from "../../components/reply/ReplyFavorDialog.vue";

const postRouteName = PostRouteName
const route = useRoute();
const router = useRouter();
const accountStore = useAccountStore();
const topicReadStore = useTopicReadStore()

// 传入参数
const tid = ref<number>()
const pid = ref<number>()
const page = ref<number | "e">()
const currentPage = ref<number>()
const authorId = ref<number>()
const to = ref<string>()
const showFavorDialog = ref<boolean>()

const replyTable = ref()

const syncParams = (route: any) => {
  tid.value = route.params.tid ? Number(route.params.tid) : undefined
  pid.value = route.params.pid ? Number(route.params.pid) : undefined
  authorId.value = route.query.authorId ? Number(route.query.authorId) : undefined
  to.value = route.query.to

  const number = route.query.page ? Number(route.query.page) : 1
  if (isNaN(number)) {
    page.value = "e"
  } else {
    page.value = number
    currentPage.value = number
  }
}


// 运行时数据
const loading = ref(false)
const data = ref<TopicDetailData>()

const authorOnly = (userId: number) => router.push({query: {authorId: userId, page: 'e'}})

const meOnly = () => authorOnly(accountStore.getAccountUserId())

const goBack = () => window.history.back();

const refresh = () => request(route, true)

const requestReadTopic = async (force: boolean) => {
  const res = await topicReadStore.readTopic(tid.value!!, page.value, authorId.value, force);
  onSuccess(res, force)
}

const requestReadAnonymous = async (force: boolean) => {
  const res = await topicReadStore.readAnonymous(tid.value!!, pid.value!!, page.value, force);
  onSuccess(res, force)
}


const requestReadReply = async (force: boolean) => {
  const p = pid.value
  if (!p) return

  if (to.value) {
    const ngaLocation = await topicReadStore.toReply(p);
    console.debug("ngaLocation", ngaLocation)
    // 路由替换，不保留 to 状态
    await router.replace({name: ReplyListRoute.LIST, params: {tid: ngaLocation.tid}, query: {page: ngaLocation.page}, hash: '#P' + ngaLocation.pid})
  } else {
    //  请求单个回复内容
    const res = await topicReadStore.readReply(p, force);

    onSuccess(res, force)
  }
}

// 请求成功
const onSuccess = (res: TopicDetailData, force: boolean) => {
  console.log('主题详情', res)

  // 对填充缺失楼层
  if (!res.topic.reversed && !res.topic.scoreTopic) {
    // 当前页可见的最后一个楼层号
    const lastFloor = res.replies[res.replies.length - 1]?.floorNumber || 0
    // 当前页实际上最后一个楼层号
    const realLastFloor = res.totalPage > res.page ? (res.page) * 20 - 1 : Math.max(res.total - 1, lastFloor)
    const firstFloor = (res.page - 1) * 20

    for (let i = firstFloor; i < realLastFloor + 1; i++) {
      const re = res.replies.find(it => it.floorNumber == i);
      if (!re) {
        const content = '[b][color=red]本条回复不可见，可能状态: 审核中 / 审核不通过 / 隐藏[/color][/b]';
        const placeholder = {
          floorNumber: i,
          content: content,
          nodes: parseContent(content)
        }
        res.replies.push(placeholder as ReplyInfo)
      }
    }
    res.replies.sort((a, b) => a.floorNumber - b.floorNumber)
  }

  data.value = res;
  // 更新页数
  page.value = res.page
  currentPage.value = res.page

  setWindowTitle(res.topic.title)

  // 检查hash，是否滚动
  if (!force && route.hash) {
    nextTick(() => {
      console.debug('滚动', route.hash)
      const pid = /#(P\d+)/.exec(route.hash)?.[1]
      const floor = /#(F\d+)/.exec(route.hash)?.[1]
      if (pid) {
        scrollToElementBatch(pid)
      }
      if (floor) {
        scrollToElementBatch(floor)
      }
    })
  }
}

const request = async (route: any, force: boolean) => {
  // console.log(route)
  syncParams(route)
  loading.value = true

  // 根据路由名称执行请求
  try {
    switch (route.name) {
      case ReplyListRoute.LIST: {
        await requestReadTopic(force)
        break
      }
      case ReplyListRoute.SINGLE: {
        await requestReadReply(force)
        break
      }
      case ReplyListRoute.ANONYMOUS: {
        await requestReadAnonymous(force)
        break
      }
    }
  } catch (e: any) {
    if (e.error) {
      const {code, message} = e.error
      ElMessage.error(`${code}:${message} 即将后退`)
      setTimeout(() => goBack(), 500)
    } else {
      console.error(e)
    }
  }
  loading.value = false
}
const quitTopic = () => {
  scrollToTop()
  const colTid = data.value?.topic?.colTopic?.topicId
  const fid = data.value?.topic.forumId;
  // 退出到合集
  if (colTid) {
    router.push({name: TopicListRoute.COL_LIST, params: {stid: colTid}})
  } else if (fid) {
    router.push({name: TopicListRoute.FORUM_LIST, params: {fid: fid}})
  }
}

const changePage = (p: number | undefined | 'e') => {
  if (!p) return
  scrollToTop()
  page.value = p
  return router.push({query: {...route.query, page: p}, params: route.params});
}

const showLevels = () => {
  const levels = data.value?.levels;
  if (levels) {
    ElMessageBox.alert(levels.map(({name, rank}) => `${name}: ${rank}`).join(' \n'), "自定义声望等级", {
      customClass: 'alert-message',
      closeOnClickModal: true,
      closeOnPressEscape: true
    })
  } else {
    ElMessage.warning('当前无自定义声望等级')
  }
}

const postReply = () => router.push({name: postRouteName, params: {action: 'reply'}, query: {tid: tid.value}})

// 快捷键
const shortKeys: ShortKey[] = [
  {title: '刷新', keys: ['alt', 'r'], action: refresh},
  ...scrollShortKeys,
  {title: '回复主楼', keys: ['shift', 'r'], action: postReply},
  {title: '退出主题到合集或版面', keys: ['shift', 'q'], action: quitTopic},
  {title: '向左翻页', keys: ['a'], action: () => pageOffset(-1)},
  {title: '向右翻页', keys: ['d'], action: () => pageOffset(1)},
  {title: '翻到第一页', keys: ['shift', 'a'], action: () => changePage(1)},
  {title: '翻到最后一页', keys: ['shift', 'd'], action: () => changePage('e')},
]

// 翻页
const pageOffset = (offset: number) => {
  const p = data.value?.page || page.value
  const total = data.value?.totalPage

  // 不符合要求，不执行
  if (!p || !total || p === 'e') return

  const target = p + offset
  if (target > 0 && target <= total) {
    changePage(target)
  }
}

const jumpToFloorNumber = () => {
  if (!data.value) return
  const maxFloor = data.value.total - 1

  ElMessageBox.prompt(`请输入楼层号 1 ~ ${maxFloor}`, "楼层跳转", {
    inputType: "number",
    inputValue: maxFloor.toString(),
    inputErrorMessage: '只能填写指定范围的楼层号',
    inputValidator: (value: string) => {
      const n = Number(value)
      if (isNaN(n)) {
        return false;
      }
      return n >= 1 && n <= maxFloor;
    },
  }).then(({value}) => {
    const page = Math.ceil((Number(value) + 1) / 20)
    console.log('page', page)
    // 跳转
    router.push({query: {...route.query, page}, params: route.params, hash: '#F' + value});
  })
}


onMounted(() => request(route, false))
watch(route, (r) => request(r, false))
</script>

<template>
  <!--快捷键-->
  <div v-if="!replyTable?.showPostDialog" class="short-key-div">
    <template v-for="k in shortKeys">
      <span v-shortkey="k.keys" @shortkey="k.action">{{ k.title }}</span>
    </template>
  </div>
  <div v-loading="loading" class="nav-bg-color route-root">
    <div style="padding: 10px">
      <el-breadcrumb separator="/">
        <!--版面-->
        <el-breadcrumb-item v-if="data">
          <forum-route :fid="data.topic.forumId">
            {{ data.forumName }}
          </forum-route>
        </el-breadcrumb-item>
        <el-breadcrumb-item v-if="data?.topic?.colTopic">
          <col-route :stid="data.topic.colTopic.topicId!!">
            {{ data.topic.colTopic.title }}
          </col-route>
        </el-breadcrumb-item>
        <el-breadcrumb-item v-if="data">
          <topic-read-route :tid="tid || data.topic.topicId">
            {{ data.topic.title }}
          </topic-read-route>
        </el-breadcrumb-item>
      </el-breadcrumb>
    </div>

    <el-page-header @back="goBack">
      <template #extra>
        <!--  按钮组-->
        <el-button-group v-if="data" size="small">
          <el-dropdown>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="copyText(topicUrl(data.topic.topicId),'官方地址')">官方地址</el-dropdown-item>
                <el-dropdown-item @click="copyText(topicCode(data.topic.topicId,data.topic.title),'论坛代码')">论坛代码</el-dropdown-item>
              </el-dropdown-menu>
            </template>
            <el-button type="primary">分享</el-button>
          </el-dropdown>
          <el-button type="primary" @click="jumpToFloorNumber">楼层跳转</el-button>
          <el-button v-if="!authorId" type="primary" @click="meOnly">只看我</el-button>
          <el-button type="primary" @click="showLevels">声望</el-button>
          <el-button type="primary" @click="showShortKeys(shortKeys)">热键</el-button>
          <el-button type="primary" @click="showFavorDialog=true">收藏</el-button>
          <el-button type="primary" @click="refresh">刷新</el-button>
          <el-button type="primary" @click="postReply">回复</el-button>
        </el-button-group>
      </template>
    </el-page-header>
    <div v-if="data">
      <el-pagination :current-page="currentPage" :page-size="data.size" :total="data.total"
                     hide-on-single-page
                     layout="prev, pager, next,jumper, total"
                     @current-change="changePage"/>
    </div>
    <div v-if="data">
      <reply-table ref="replyTable" :levels="data.levels"
                   :replies="data.replies"
                   :topic="data.topic"
                   :user-map="data.userMap"
                   @refresh="refresh"/>
    </div>
    <div v-if="data">
      <el-pagination :current-page="currentPage" :page-size="data.size" :total="data.total"
                     hide-on-single-page
                     layout="prev, pager, next,jumper, total"
                     @current-change="changePage"/>
    </div>

    <div v-if="data">
      <reply-favor-dialog v-model="showFavorDialog" :tid="data.topic.topicId"/>
    </div>
  </div>
</template>

<style scoped>

</style>